package com.atguigu.tingshu.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.atguigu.tingshu.album.AlbumFeignClient;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.user.*;
import com.atguigu.tingshu.user.mapper.*;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.user.service.UserPaidTrackService;
import com.atguigu.tingshu.user.strategy.ItemTypeStrategy;
import com.atguigu.tingshu.user.strategy.StrategyFactory;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

	@Autowired
	private UserInfoMapper userInfoMapper;

    @Autowired
    private WxMaService wxMaService;

    @Autowired
    private RabbitService rabbitService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserPaidAlbumMapper userPaidAlbumMapper;

    @Autowired
    private UserPaidTrackMapper userPaidTrackMapper;

    @Autowired
    private VipServiceConfigMapper vipServiceConfigMapper;

    @Autowired
    private UserVipServiceMapper userVipServiceMapper;

    @Autowired
    private AlbumFeignClient albumFeignClient;

    @Autowired
    private StrategyFactory strategyFactory;

    @Override
    public Map<String, String> wxLogin(String code) {
        try {
            //获取微信登录信息
            WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code);
            if(sessionInfo != null){
                //获得微信登录唯一应用id openid
                String openid = sessionInfo.getOpenid();

                //判断用户是否存在
                UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getWxOpenId, openid));
                if (userInfo == null){
                    //用户不存在就注册
                    userInfo = new UserInfo();
                    userInfo.setWxOpenId(openid);
                    userInfo.setNickname("听友" + IdUtil.getSnowflakeNextId());
                    userInfo.setAvatarUrl("https://img.ixintu.com/download/jpg/20200901/3e9ce3813b7199ea9588eeb920f41208_512_512.jpg!bg");
                    userInfo.setIsVip(0);
                    userInfoMapper.insert(userInfo);
                    //给account发信息创建新的用户账号
                    rabbitService.sendMessage(MqConst.EXCHANGE_USER, MqConst.ROUTING_USER_REGISTER, userInfo.getId());
                }
                //新建token
                String token = IdUtil.getSnowflakeNextIdStr();
                //存入redis当中
                String loginKey = RedisConstant.USER_LOGIN_KEY_PREFIX + token;
                UserInfoVo userInfoVo = BeanUtil.copyProperties(userInfo, UserInfoVo.class);
                redisTemplate.opsForValue().set(loginKey, userInfoVo, RedisConstant.USER_LOGIN_KEY_TIMEOUT, TimeUnit.SECONDS);
                //把token返回前端
                HashMap<String, String> resultMap = new HashMap<>();
                resultMap.put("token", token);
                return resultMap;
            }
            return null;
        } catch (Exception e) {
            log.error("[用户服务]微信登录异常：{}", e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 修改用户信息
     * @param userId
     * @param userInfoVo
     */
    @Override
    public void updateUser(Long userId, UserInfoVo userInfoVo, String token) {
        UserInfo userInfo = userInfoMapper.selectById(userId);
        userInfo.setNickname(userInfoVo.getNickname());
        userInfo.setAvatarUrl(userInfoVo.getAvatarUrl());
        userInfoMapper.updateById(userInfo);

        //准备更新数据
        BeanUtils.copyProperties(userInfo,userInfoVo);
        //定义存储key
        String loginKey=RedisConstant.USER_LOGIN_KEY_PREFIX+token;
        //更新覆盖原来数据
        redisTemplate.opsForValue().set(loginKey,userInfoVo,RedisConstant.USER_LOGIN_KEY_TIMEOUT,TimeUnit.SECONDS);
    }

    /**
     * 根据用户ID查询用户信息
     * @param userId
     * @return
     */
    @Override
    public UserInfoVo getUserInfoVo(Long userId) {
        UserInfo userInfo = userInfoMapper.selectById(userId);
        UserInfoVo userInfoVo = BeanUtil.copyProperties(userInfo, UserInfoVo.class);
        return userInfoVo;
    }

    /**
     * 获取用户声音列表付费情况
     * @param userId
     * @param albumId
     * @param trackIdList
     * @return
     */
    @Override
    public Map<Long, Integer> getUserIsPaidTrack(Long userId, Long albumId, List<Long> trackIdList) {
        HashMap<Long, Integer> mapResult = new HashMap<>();
        //判断是否购买专辑
        Long paidAlbumNum = userPaidAlbumMapper.selectCount(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getUserId, userId).eq(UserPaidAlbum::getAlbumId, albumId));
        if (paidAlbumNum > 0){
            for (Long trackId : trackIdList) {
                mapResult.put(trackId, 1); // 键：id，值：name
            }
            return mapResult;
        }
        //判断是否购买声音
        List<UserPaidTrack> userPaidTracks = userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>()
                .eq(UserPaidTrack::getUserId, userId)
                .eq(UserPaidTrack::getAlbumId, albumId)
                .in(UserPaidTrack::getTrackId, trackIdList));
        if (userPaidTracks == null){
            for (Long trackId : trackIdList) {
                mapResult.put(trackId, 0); // 键：id，值：name
            }
            return mapResult;
        }
        List<Long> paidTrackIdList = userPaidTracks.stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
        for (Long trackId : trackIdList) {
            if (paidTrackIdList.contains(trackId)){
                mapResult.put(trackId, 1);
            }else {
                mapResult.put(trackId, 0);
            }
        }
        return mapResult;
    }

    /**
     * 判断用户是否购买过指定专辑
     * @param albumId
     * @return
     */
    @Override
    public Boolean getUserIsPaidAlbum(Long albumId) {
        Long userId = AuthContextHolder.getUserId();
        Long count = userPaidAlbumMapper.selectCount(new QueryWrapper<UserPaidAlbum>().eq("user_id", userId).eq("album_id", albumId));
        return count > 0;
    }

    /**
     * 新增购买记录
     * @param userPaidRecordVo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void savePaidRecord(UserPaidRecordVo userPaidRecordVo) {
        ItemTypeStrategy strategy = strategyFactory.getStrategy(userPaidRecordVo.getItemType());
        strategy.savePaidRecord(userPaidRecordVo);
    }

    /**
     * 更新用户会员状态
     */
    @Override
    public void updateVipExpireStatus() {
        userInfoMapper.updateVipExpireStatus();
    }


}
